package com.codyy.lib_common.base.viewmodel

import android.view.View
import androidx.lifecycle.*
import com.kennyc.view.MultiStateView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import java.io.EOFException
import java.net.BindException
import java.net.ConnectException
import java.net.SocketException
import java.net.UnknownHostException

open class BaseViewModel : ViewModel() {

    val mStateLiveData =
        MutableLiveData(MultiStateView.ViewState.LOADING)//通用事件模型驱动(如：显示对话框、取消对话框、错误提示)

    fun launch(block: suspend CoroutineScope.() -> Unit) {//使用协程封装统一的网络请求处理
        launch(block, null)
    }

    fun launch(
        block: suspend CoroutineScope.() -> Unit,
        error: (suspend (Throwable) -> Unit)?
    ) {//使用协程封装统一的网络请求处理
        viewModelScope.launch {
            //ViewModel自带的viewModelScope.launch,会在页面销毁的时候自动取消请求,有效封装内存泄露
            try {
                mStateLiveData.value = MultiStateView.ViewState.LOADING
                block()
                mStateLiveData.value = MultiStateView.ViewState.CONTENT
            } catch (e: Exception) {
                error?.let { it(e) }
                when (e) {
                    is UnknownHostException, is SocketException, is EOFException, is ConnectException, is BindException -> {
                        mStateLiveData.value = MultiStateView.ViewState.NONETWORK
                    }
                    else -> {
                        mStateLiveData.value = MultiStateView.ViewState.ERROR
                    }
                }

            }
        }
    }

    fun <T> emit(block: suspend LiveDataScope<T>.() -> T): LiveData<T> = liveData {
        try {
            mStateLiveData.value = MultiStateView.ViewState.LOADING
            emit(block())
            mStateLiveData.value = MultiStateView.ViewState.CONTENT
        } catch (e: Exception) {
            when (e) {
                is UnknownHostException, is SocketException, is EOFException, is ConnectException, is BindException -> {
                    mStateLiveData.value = MultiStateView.ViewState.NONETWORK
                }
                else -> {
                    mStateLiveData.value = MultiStateView.ViewState.ERROR
                }
            }
        }
    }

    fun isShowContent(): Int = if (mStateLiveData.value == MultiStateView.ViewState.CONTENT) {
        View.VISIBLE
    } else {
        View.GONE
    }
}